function $(i) {return document.getElementById(i);};

/*
 *	ラジオボタンの選択されているインデックスを取得する。<br/>
 *	何も選択されていない場合はnullを返す。
 */
function getSelectedIndex(name) {
	var radio = document.getElementsByName(name);
	if (radio.length) {
		for(var i=0, l=radio.length; i<l; i++) {
			if (radio[i].checked) return i.toString();
		}
	}
	return null;
}

document.body.onload = function() {

	$("distText").value = "";

	// コピー、ペースト非対応ブラウザ(Chrome)の場合はボタン非表示
	if (!(document.all && self.clipboardData)) {
		$("pasteText").style.display = "none";
		$("copyText").style.display = "none";
	};
	
	// クリップボードから変換文字列テキストに貼り付ける
	$("pasteText").onclick = function pasteText() {

		var textarea = $("srcText");

		try {

			textarea.select();

			if (document.all && self.clipboardData) {
				var data = clipboardData.getData("text");
				if (data) textarea.value = data;
				return;
			}

			if (document.body.createTextRange) {
				var textRange = document.body.createTextRange();
				textRange.moveToElementText(textarea);
				textRange.execCommand("paste");
				return;
			}

		} catch (ex) {
			alert("*** JavaScriptエラー ***\n\n" + ex.toString());
		}

		alert("JavaScriptによる貼り付けがサポートされていません。");
	};

	// 出力文字列テキストをクリップボードに設定する
	$("copyText").onclick = function pasteText() {
	
		var textarea = $("distText");

		if (!textarea.value) return;

		try {

			textarea.select();

			if (document.all && self.clipboardData) {
				clipboardData.setData("text", textarea.value);
				return;
			}

			if (document.body.createTextRange) {
				var textRange = document.body.createTextRange();
				textRange.moveToElementText(textarea);
				textRange.execCommand("copy");
				return;
			}

		} catch (ex) {
			alert("*** JavaScriptエラー ***\n\n" + ex.toString());
		}

		alert("JavaScriptによるコピーがサポートされていません。");
	};

	// トグルボタン表示切り替え
	var convertTypeChange = function () {
		if ($("reverseCamel").checked) {
			$("toggleUpper").style.display = "inline";
			$("toggleLower").style.display = "inline";
		} else {
			$("toggleUpper").style.display = "none";
			$("toggleLower").style.display = "none";
		}
	};
	$("lowerCamel").onclick = convertTypeChange;
	$("upperCamel").onclick = convertTypeChange;
	$("reverseCamel").onclick = convertTypeChange;
	$("labelReverseCamel").onclick = convertTypeChange;
	$("labelLowerCamel").onclick = convertTypeChange;
	$("labelUpperCamel").onclick = convertTypeChange;
	$("lowerCamel").onclick();

	// オプション非表示
	$("hideOptions").onclick = function hideOptions() {
		$("showOptions").style.display = "inline";
		$("delimRow").style.display = "none";
		$("presuffixRow").style.display = "none";
		this.style.display = "none";
	};
	$("hideOptions").onclick();
	
	// オプション表示
	$("showOptions").onclick = function showOptions() {
		this.style.display = "none";
		$("delimRow").style.display = "block";
		$("presuffixRow").style.display = "block";
		$("hideOptions").style.display = "inline";
	};

	// 改行チェックボックスの状態によりチェックボックスを制御
	$("isCrLf").onclick = function () {
		var isCrLf = $("isCrLf");
		if (isCrLf.checked) {
			$("labelCrLfTop").style.color = "#000000";
			$("labelIndent").style.color = "#000000";
			$("isCrLfTop").disabled = false;
			$("isIndent").disabled = false;
		} else {
			$("labelCrLfTop").style.color = "#c0c0c0";
			$("labelIndent").style.color = "#c0c0c0";
			$("labelTabWidth").style.color = "#c0c0c0";
			$("isCrLfTop").checked = false;
			$("isIndent").checked = false;
			$("isCrLfTop").disabled = true;
			$("isIndent").disabled = true;
			$("tabWidth").disabled = true;
			$("tabWidth").readonly = true;
			$("tabWidth").value = "";
		}
	};
	$("labelCrLf").onclick = $("isCrLf").onclick;
	$("isCrLf").onclick();

	// インデントチェックボックスの状態によりタブ幅を制御
	$("isIndent").onclick = function () {
		var isIndent = $("isIndent");
		if (isIndent.disabled) return;
		var tabWidth = $("tabWidth");
		if (isIndent.checked) {
			$("labelTabWidth").style.color = "#000000";
			tabWidth.disabled = false;
			tabWidth.readonly = false;
			if (!tabWidth.value) tabWidth.value = "4";
		} else {
			$("labelTabWidth").style.color = "#c0c0c0";
			tabWidth.disabled = true;
			tabWidth.readonly = true;
			tabWidth.value = "";
		}
	};
	$("labelIndent").onclick = $("isIndent").onclick;
	$("isIndent").onclick();

	// その他チェックボックスの状態によりその他テキストを制御
	$("isOther").onclick = function () {
		var isOther = $("isOther");
		if (isOther.checked) {
			$("otherDelim").disabled = false;
			$("otherDelim").readonly = false;
		} else {
			$("otherDelim").disabled = true;
			$("otherDelim").readonly = true;
			$("otherDelim").value = "";
		}
	};
	$("labelOther").onclick = $("isOther").onclick;
	$("isOther").onclick();

	// prefix, suffixの内容でラベルを制御
	$("prefix").onchange = function () {
		$("labelPrefix").innerHTML = this.value;
	};
	$("suffix").onchange = function () {
		$("labelSuffix").innerHTML = this.value;
	};
	$("prefix").onchange();
	$("suffix").onchange();

	// 変換ボタン処理は関数が長いので別定義
	$("execConvert").onclick = execMain;

	// トグルボタン押下処理
	$("toggleUpper").onmousedown = toggleDown;
	$("toggleLower").onmousedown = toggleDown;

	// トグルボタンホバー処理
	if ($("toggleUpper").onmouseenter) {
		$("toggleUpper").onmouseenter = toggleEnter;
		$("toggleUpper").onmouseleave = toggleLeave;
	} else {
		$("toggleUpper").onmouseover = toggleEnter;
		$("toggleUpper").onmouseout = toggleLeave;
	}
	if ($("toggleLower").onmouseenter) {
		$("toggleLower").onmouseenter = toggleEnter;
		$("toggleLower").onmouseleave = toggleLeave;
	} else {
		$("toggleLower").onmouseover = toggleEnter;
		$("toggleLower").onmouseout = toggleLeave;
	}

	// トグルボタン初期化
	$("toggleUpper").value = "on";
	$("toggleLower").value = "off";
}

// 変換メイン処理
function execMain() {
	try {
		// 画面入力データを取得
		var convParam = createConvertParameter();

		// nullの場合は処理終了
		if (!convParam) return;
		
		// 変換処理実行
		var convertText = execConvert(convParam);

		
		// 出力文字のCaseを設定
		if ($("reverseCamel").checked) {
			if ($("toggleUpper").value == "on") {
				convertText = convertText.toUpperCase();
			} else if ($("toggleLower").value == "on") {
				convertText = convertText.toLowerCase();
			}
		}

		$("distText").value = convertText;

	} catch (ex) {
		alert("*** JavaScriptエラー ***\n\n" + ex.toString());
	}
}

/*
 *	画面入力データから変換用パラメータを生成する。
 */
function createConvertParameter(srcText) {

	var convertParam = {};

	convertParam.srcText = $("srcText").value;

	// 何も入力されていなければnullを返す
	if (!convertParam.srcText) {
		alert("変換文字列が入力されていません。");
		return null;
	}

	// 変換メソッドを取得
	convertParam.converter = getConverter();

	// prefixとsuffixを取得
	convertParam = setPrefixSuffix(convertParam);

	// 区切り文字を取得
	convertParam.delim = getDelimiter();

	// タブ幅を初期化
	convertParam.tabLength = 0;

	// インデントが選択されていた場合はタブ幅を設定
	if ($("isIndent").checked) {
		convertParam.tabLength = $("tabWidth").value||"4";
		if (isNaN(convertParam.tabLength) || convertParam.tabLength < 1
			|| convertParam.tabLength.indexOf(".") > 0) {
			alert("タブ幅は正の整数で入力してください");
			return null;
		}
	}

	return convertParam;
}

/*
 *	変換メソッドを返す。
 */
function getConverter() {
	var convertType = getSelectedIndex("convertType");
	switch (convertType) {
		case ConvertType.LOWER_CAMEL  :
			return Camerizer.lowerCamerize;
		case ConvertType.UPPER_CAMEL  :
			return Camerizer.upperCamerize;
		case ConvertType.REVERSE_CAMEL:
			return Camerizer.reverseCamerize;
	}
	throw "サポートされていない変換方式です。";
}

/*
 *	PrefixとSuffixを設定する。
 */
function setPrefixSuffix(param) {
	var roundType = getSelectedIndex("round");
	switch (roundType) {
		case RoundType.DQ     :
			param.prefix = '"';
			param.suffix = '"';
			break;
		case RoundType.SQ     :
			param.prefix = "'";
			param.suffix = "'";
			break;
		case RoundType.COLON  :
			param.prefix = ":";
			break;
		case RoundType.AT_MARK:
			param.prefix = "@";
			break;
		case RoundType.SHARP  :
			param.prefix = "#";
			param.suffix = "#";
			break;
        case RoundType.DOLLER :
			param.prefix = "$";
			param.suffix = "$";
			break;
		case RoundType.OTHER  :
			param.prefix = $("prefix").value;
			param.suffix = $("suffix").value;
			break;
	}
	if(!param.prefix) param.prefix = "";
	if(!param.suffix) param.suffix = "";
	return param;
}

/*
 *	区切り文字を取得する。
 */
function getDelimiter() {
	var delim = "";
	if ($("isComma").checked) delim += ",";
	if ($("isSpace").checked) delim += " ";
	if ($("isOther").checked) delim += $("otherDelim").value;
	if($("isCrLf").checked) {
		if ($("isCrLfTop").checked) {
			delim = "\n" + delim;
		} else {
			delim += "\n";
		}
	}
	return delim;
}

/*
 *	変換処理実行
 */
function execConvert(param) {

	var reg = new RegExp(/[a-z_][a-z0-9_]*/gim);
	var matches = param.srcText.match(reg);

	if (!matches) {
		throw "変換可能な文字が含まれていません。";
	}

	this.list = [];

	var addText = function (param, text) {
		try {
			var value = param.prefix + param.converter(text) + param.suffix;
			this.list.push(value);
		} catch (ex) {
			this.list.push(text);
		}
	}

	if (!matches.length) {
		addText(param, matches);
	} else {
		for (var i=0, l=matches.length; i<l; i++) {
			addText(param, matches[i]);
		}
	}

	// デリミタが設定されている場合
	if (param.delim) {
	
		// リストをデリミタで連結
		var convertText = this.list.join(param.delim);

		// インデントが指定されている場合
		if (param.tabLength > 0) {
			this.list = convertText.split("\n");
			var tab = "";
			for(var i=0, l=param.tabLength; i<l; i++) {tab += " "};
			convertText = tab + this.list.join("\n" + tab);
		}

		return convertText;

	} else {
		return this.list.join(", "); // TODO 元のテキストに埋め込む
	}
}

/*
 *	トグルボタンマウスダウン
 */
function toggleDown() {
	if (this.value && this.value == "on") {
		return;
	}
	this.value = "on";
	this.className = "toggle_on";
	var tgl = null;
	if (this.id == "toggleUpper") {
		tgl = $("toggleLower");
		$("distText").value = $("distText").value.toUpperCase();
	} else if (this.id == "toggleLower") {
		tgl = $("toggleUpper");
		$("distText").value = $("distText").value.toLowerCase();
	} else {
		return;
	}
	tgl.value = "off";
	tgl.className = "toggle_off";
}

/*
 *	トグルボタンマウスオーバー
 */
function toggleEnter() {
	if (this.value && this.value == "off") {
		this.className = "toggle_enter";
	}
}

/*
 *	トグルボタンマウスアウト
 */
function toggleLeave() {
	if (this.value && this.value == "off") {
		this.className = "toggle_off";
	}
}

